package com.finance.cooperate.feature.service.impl;

import com.alibaba.fastjson.JSON;
import com.finance.cooperate.common.annotation.RetryDot;
import com.finance.cooperate.common.enumerate.ScrapyAppCategoriesEnum;
import com.finance.cooperate.common.properties.ApiProperties;
import com.finance.cooperate.common.properties.CooperateProperties;
import com.finance.cooperate.common.utils.DateUtils;
import com.finance.cooperate.common.utils.HttpClientUtil;
import com.finance.cooperate.common.utils.StringUtil;
import com.finance.cooperate.dao.entity.primary.App;
import com.finance.cooperate.dao.local.cache.ScrapyCache;
import com.finance.cooperate.dao.local.scope.CooperateRequestScope;
import com.finance.cooperate.dao.repository.primary.AppRepository;
import com.finance.cooperate.dao.support.dto.ScrapyAppCategoriesDTO;
import com.finance.cooperate.feature.core.service.ScrapyAppsCacheService;
import com.finance.cooperate.feature.dto.ScrapyAppsDTO;
import com.finance.cooperate.feature.dto.ScrapyAppsMapDTO;
import com.finance.cooperate.feature.service.ScrapyAppsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class ScrapyAppsServiceImpl implements ScrapyAppsService {

    @Autowired
    private AppRepository appRepository;

    @Autowired
    private CooperateRequestScope requestScope;

    @Autowired
    private ScrapyAppsCacheService scrapyAppsCacheService;

    @Autowired
    private CooperateProperties cooperateProperties;

    @Override
    public ScrapyAppsDTO getInfo(String uid) {

        ScrapyAppsDTO dto = new ScrapyAppsDTO();

        Date lastSubmitTime = requestScope.getLastSubmitTime();

        List<App> appList = appRepository.getCurrentApp(uid, requestScope.getDeviceId(), lastSubmitTime);


        // 各类目安装app数统计
        dto = this.getCategoriesCount(dto, appList, lastSubmitTime);

        // 获取 top N 的 app 个数
        dto = this.getTopRankCount(dto, appList, lastSubmitTime);

        // 各类目详细统计
        dto = this.getCategoriesMap(dto, appList, lastSubmitTime);

        // 金融类 app 统计
        dto = this.getFinanceAppCount(dto, appList, lastSubmitTime);

        try {

            ScrapyAppsServiceImpl proxy = (ScrapyAppsServiceImpl) AopContext.currentProxy();

            // app 类别CNN分
            Double appScore01 = proxy.cnnScore01(appList, lastSubmitTime);

            dto.setAppScore01(appScore01);


        } catch (Exception e) {
            log.error("请求 python 服务出现异常:" + uid, e);
        }


        return dto;
    }


    /**
    * @Author shenanxin
    * @Description 金融类app相关统计
    * @Date 16:54 2023/9/19
    * @Param [dto, appList, lastSubmitTime]
    * @return com.finance.cooperate.feature.dto.ScrapyAppsDTO
    **/
    private ScrapyAppsDTO getFinanceAppCount(ScrapyAppsDTO dto, List<App> appList, Date lastSubmitTime) {

        if (appList.size() > 0) {

            // 防止多次遍历
            Map<String, String> appPackageMap = new HashMap<>();
            for (App app: appList) {
                String packageName = app.getAppPackageName();
                appPackageMap.put(packageName.toLowerCase(), app.getFirstInstallTime());
            }

            List<ScrapyAppCategoriesDTO> scrapyAppLists = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Finance.getCode());

            Integer financeCount1W = 0;
            Integer financeCount = 0;
            for (ScrapyAppCategoriesDTO scrapy: scrapyAppLists) {

                if (appPackageMap.containsKey(scrapy.getStoresId().toLowerCase())) {

                    String installTime = appPackageMap.get(scrapy.getStoresId().toLowerCase());

                    Integer diffDays = DateUtils.getTimeDiffDays(DateUtils.toDate(installTime), lastSubmitTime);


                    if (diffDays < 7) {
                        financeCount1W ++;
                    }

                    financeCount ++;

                }
            }


            dto.setFinanceCount1W(financeCount1W);
            dto.setFinanceRate((double) financeCount / appList.size());

        }


        return dto;

    }


    /**
    * @Author shenanxin
    * @Description 深度学习模型分
    * @Date 09:27 2023/10/18
    * @Param [appList, lastSubmitTime]
    * @return java.lang.Double
    **/
    @RetryDot
    public Double cnnScore01(List<App> appList, Date lastSubmitTime) throws Exception {

        Double score = null;

        // 爬虫app 字典定义{app_type, [app_install_time_01, app_install_time_02, ...]}
        Map<String, List<String>> appDict = new HashMap<>();

        for (App app: appList) {

            // 所有类目
            List<String> listType = appDict.getOrDefault("all_type", new ArrayList<String>());
            listType.add(app.getFirstInstallTime());
            appDict.put("all_type", listType);

            String packageName = app.getAppPackageName();

            if (!StringUtil.isEmptyOrNvl(packageName)) {

                // 爬虫类别遍历
                ScrapyAppCategoriesEnum[] enums = ScrapyAppCategoriesEnum.values();

                for (ScrapyAppCategoriesEnum e : enums) {

                    if (e == ScrapyAppCategoriesEnum.Top_Overall || e == ScrapyAppCategoriesEnum.Art_Design
                            || e == ScrapyAppCategoriesEnum.Auto_Vehicles || e == ScrapyAppCategoriesEnum.Beauty
                            || e == ScrapyAppCategoriesEnum.Books_Reference || e == ScrapyAppCategoriesEnum.Business
                            || e == ScrapyAppCategoriesEnum.Comics || e == ScrapyAppCategoriesEnum.Dating
                            || e == ScrapyAppCategoriesEnum.Education || e == ScrapyAppCategoriesEnum.Events
                            || e == ScrapyAppCategoriesEnum.Family || e == ScrapyAppCategoriesEnum.Health_Fitness
                            || e == ScrapyAppCategoriesEnum.House_Home || e == ScrapyAppCategoriesEnum.Libraries_Demo
                            || e == ScrapyAppCategoriesEnum.Lifestyle || e == ScrapyAppCategoriesEnum.Maps_Navigation
                            || e == ScrapyAppCategoriesEnum.Medical  || e == ScrapyAppCategoriesEnum.Parenting
                            || e == ScrapyAppCategoriesEnum.Personalization || e == ScrapyAppCategoriesEnum.Photography
                            || e == ScrapyAppCategoriesEnum.Social || e == ScrapyAppCategoriesEnum.Sports
                            || e == ScrapyAppCategoriesEnum.Top_Apps || e == ScrapyAppCategoriesEnum.Top_New
                            || e == ScrapyAppCategoriesEnum.Travel_Local || e == ScrapyAppCategoriesEnum.Weather
                    ) {

                        continue;
                    }


                    List<ScrapyAppCategoriesDTO> scrapyAppLists = scrapyAppsCacheService.getByCategories(e.getCode());


                    for (ScrapyAppCategoriesDTO scrapy: scrapyAppLists) {

                        if (packageName.toLowerCase().equals(scrapy.getStoresId().toLowerCase())) {// 匹配上了

                            Optional<ScrapyAppCategoriesEnum> optional = Arrays.stream(ScrapyAppCategoriesEnum.values())
                                    .filter(o -> o.getCode().equals(scrapy.getCategoriesId()))
                                    .findFirst();

                            if (optional.isPresent()) {


                                ScrapyAppCategoriesEnum anEnum = optional.get();

                                if (anEnum == ScrapyAppCategoriesEnum.Android_Wear) {

                                    List<String> list = appDict.getOrDefault("android_wear", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("android_wear", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Communication) {

                                    List<String> list = appDict.getOrDefault("communication", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("communication", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Entertainment) {

                                    List<String> list = appDict.getOrDefault("entertainment", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("entertainment", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Finance) {

                                    List<String> list = appDict.getOrDefault("finance", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("finance", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Food_Drink) {

                                    List<String> list = appDict.getOrDefault("food_drink", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("food_drink", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Games) {

                                    List<String> list = appDict.getOrDefault("games", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("games", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Music_Audio) {

                                    List<String> list = appDict.getOrDefault("music_audio", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("music_audio", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.News_Magazines) {

                                    List<String> list = appDict.getOrDefault("news_magazines", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("news_magazines", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Productivity) {

                                    List<String> list = appDict.getOrDefault("productivity", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("productivity", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Shopping) {

                                    List<String> list = appDict.getOrDefault("shopping", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("shopping", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Tools) {

                                    List<String> list = appDict.getOrDefault("tools", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("tools", list);

                                } else if (anEnum == ScrapyAppCategoriesEnum.Video_Players_Editors) {

                                    List<String> list = appDict.getOrDefault("video_players_editors", new ArrayList<String>());
                                    list.add(app.getFirstInstallTime());
                                    appDict.put("video_players_editors", list);

                                }

                            }

                            break;
                        }
                    }
                }
            }

        }

        // 请求 python 模型
        if (!appDict.isEmpty()) {

            ApiProperties api = cooperateProperties.getApi();

            // 封装参数
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("submit_time", DateUtils.toStr(lastSubmitTime));
            params.put("f_scrapy_data", JSON.toJSONString(appDict));

            String reqResult = HttpClientUtil.doPostJson(api.getSubModelUrl() + api.getApp01().getUrl(), JSON.toJSONString(params));

            if (!StringUtil.isEmptyOrNvl(reqResult)) {

                score = Double.parseDouble(reqResult);

            }

        }

        return score;

    }



    /**
     * @Author shen
     * @Description 获取 top N 的 app 个数
     * @Date 16:21 2022/9/15
     * @Param [dto, appList, lastSubmitTime]
     * @return com.finance.cooperate.feature.dto.ScrapyAppsDTO
     **/
    private ScrapyAppsDTO getTopRankCount(ScrapyAppsDTO dto, List<App> appList, Date lastSubmitTime) {

        Integer topOverallTop50Count =  0, topNewTop50Count = 0, topAppsTop50Count = 0, financeTop100Count = 0, financeTop50Count = 0, financeTop10Count = 0;


        Set<String> appTempSet = new HashSet<>();
        for (App app : appList) {
            if (!StringUtil.isEmptyOrNvl(app.getAppPackageName())) {
                appTempSet.add(app.getAppPackageName().toLowerCase());
            }
        }



        List<ScrapyAppCategoriesDTO> topOverallTop50List = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Top_Overall.getCode(), 50);
        for (ScrapyAppCategoriesDTO s : topOverallTop50List) {

            if (appTempSet.contains(s.getStoresId().toLowerCase())) {
                topOverallTop50Count ++;
            }

        }

        List<ScrapyAppCategoriesDTO> topNewTop50List = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Top_New.getCode(), 50);
        for (ScrapyAppCategoriesDTO s : topNewTop50List) {
            if (appTempSet.contains(s.getStoresId().toLowerCase())) {
                topNewTop50Count ++;
            }
        }


        List<ScrapyAppCategoriesDTO> topAppsTop50List = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Top_Apps.getCode(), 50);
        for (ScrapyAppCategoriesDTO s : topAppsTop50List) {
            if (appTempSet.contains(s.getStoresId().toLowerCase())) {
                topAppsTop50Count ++;
            }
        }


        List<ScrapyAppCategoriesDTO> financeTop100List = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Finance.getCode(), 100);
        for (ScrapyAppCategoriesDTO s : financeTop100List) {
            if (appTempSet.contains(s.getStoresId().toLowerCase())) {
                financeTop100Count ++;
            }
        }


        List<ScrapyAppCategoriesDTO> financeTop50List = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Finance.getCode(), 50);
        for (ScrapyAppCategoriesDTO s : financeTop50List) {
            if (appTempSet.contains(s.getStoresId().toLowerCase())) {
                financeTop50Count ++;
            }
        }

        List<ScrapyAppCategoriesDTO> financeTop10List = scrapyAppsCacheService.getByCategories(ScrapyAppCategoriesEnum.Finance.getCode(), 10);

        for (ScrapyAppCategoriesDTO s : financeTop10List) {
            if (appTempSet.contains(s.getStoresId().toLowerCase())) {
                financeTop10Count ++;
            }
        }


        dto
                .setTopOverallTop50Count(topOverallTop50Count)
                .setNewsCount(topNewTop50Count)
                .setTopAppsTop50Count(topAppsTop50Count)
                .setFinanceTop100Count(financeTop100Count)
                .setFinanceTop50Count(financeTop50Count)
                .setFinanceTop10Count(financeTop10Count);



        return dto;
    }


    /**
     * @Author shen
     * @Description 统计各类 app 数
     * @Date 15:00 2022/9/14
     * @Param [dto, appList, lastSubmitTime]
     * @return com.finance.cooperate.feature.dto.ScrapyAppsDTO
     **/
    private ScrapyAppsDTO getCategoriesCount(ScrapyAppsDTO dto, List<App> appList, Date lastSubmitTime) {

        Integer androidWearCount = 0, artDesignCount =  0, autoVehiclesCount = 0, beautyCount = 0, booksReferenceCount = 0,
                businessCount = 0, communicationCount = 0, comicsCount = 0, datingCount = 0, educationCount = 0, entertainmentCount = 0,
                eventsCount = 0, familyCount = 0, financeCount = 0, foodCount = 0, gamesCount = 0, healthCount = 0, houseCount = 0,
                librariesCount = 0, lifestyleCount = 0, mapsCount = 0, medicalCount = 0, musicCount = 0, newsCount = 0, parentingCount = 0,
                personalizationCount = 0, photographyCount = 0, productivityCount = 0, shoppingCount = 0, socialCount = 0, sportsCount = 0,
                toolsCount = 0, travelCount = 0, videoEditorsCount = 0, weatherCount = 0;

        Set<String> appTempSet = new HashSet<>();
        for (App app : appList) {
            if (!StringUtil.isEmptyOrNvl(app.getAppPackageName())) {
                appTempSet.add(app.getAppPackageName().toLowerCase());
            }
        }

        // 爬虫类别遍历
        ScrapyAppCategoriesEnum[] enums = ScrapyAppCategoriesEnum.values();

        for (ScrapyAppCategoriesEnum e : enums) {

            if (e == ScrapyAppCategoriesEnum.Top_Overall || e == ScrapyAppCategoriesEnum.Top_Apps || e == ScrapyAppCategoriesEnum.Top_New) {
                continue;
            }

            List<ScrapyAppCategoriesDTO> scrapyAppLists = scrapyAppsCacheService.getByCategories(e.getCode());

            for (ScrapyAppCategoriesDTO scrapy: scrapyAppLists) {

                if (appTempSet.contains(scrapy.getStoresId().toLowerCase())) {// 匹配上了

                    Optional<ScrapyAppCategoriesEnum> optional = Arrays.stream(ScrapyAppCategoriesEnum.values())
                            .filter(o -> o.getCode().equals(scrapy.getCategoriesId()))
                            .findFirst();

                    if (optional.isPresent()){

                        ScrapyAppCategoriesEnum anEnum = optional.get();

                        if (anEnum == ScrapyAppCategoriesEnum.Android_Wear) {
                            androidWearCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Art_Design) {
                            artDesignCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Auto_Vehicles) {
                            autoVehiclesCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Beauty) {
                            beautyCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Books_Reference) {
                            booksReferenceCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Business) {
                            businessCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Communication) {
                            communicationCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Comics) {
                            comicsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Dating) {
                            datingCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Education) {
                            educationCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Entertainment) {
                            entertainmentCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Events) {
                            eventsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Family) {
                            familyCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Finance) {
                            financeCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Food_Drink) {
                            foodCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Games) {
                            gamesCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Health_Fitness) {
                            healthCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.House_Home) {
                            houseCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Libraries_Demo) {
                            librariesCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Lifestyle) {
                            lifestyleCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Maps_Navigation) {
                            mapsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Medical) {
                            medicalCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Music_Audio) {
                            musicCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.News_Magazines) {
                            newsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Parenting) {
                            parentingCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Personalization) {
                            personalizationCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Photography) {
                            photographyCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Productivity) {
                            productivityCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Shopping) {
                            shoppingCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Social) {
                            socialCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Sports) {
                            sportsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Tools) {
                            toolsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Travel_Local) {
                            travelCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Video_Players_Editors) {
                            videoEditorsCount ++;
                        } else if (anEnum == ScrapyAppCategoriesEnum.Weather) {
                            weatherCount ++;
                        }

                    }

                }

            }

        }

        dto
                .setAndroidWearCount(androidWearCount)
                .setArtDesignCount(artDesignCount)
                .setAutoVehiclesCount(autoVehiclesCount)
                .setBeautyCount(beautyCount)
                .setBooksReferenceCount(booksReferenceCount)
                .setBusinessCount(businessCount)
                .setCommunicationCount(communicationCount)
                .setComicsCount(comicsCount)
                .setDatingCount(datingCount)
                .setEducationCount(educationCount)
                .setEntertainmentCount(entertainmentCount)
                .setEventsCount(eventsCount)
                .setFamilyCount(familyCount)
                .setFinanceCount(financeCount)
                .setFoodCount(foodCount)
                .setGamesCount(gamesCount)
                .setHealthCount(healthCount)
                .setHouseCount(houseCount)
                .setLibrariesCount(librariesCount)
                .setLifestyleCount(lifestyleCount)
                .setMapsCount(mapsCount)
                .setMedicalCount(medicalCount)
                .setMusicCount(musicCount)
                .setNewsCount(newsCount)
                .setParentingCount(parentingCount)
                .setPersonalizationCount(personalizationCount)
                .setPhotographyCount(photographyCount)
                .setProductivityCount(productivityCount)
                .setShoppingCount(shoppingCount)
                .setSocialCount(socialCount)
                .setSportsCount(sportsCount)
                .setToolsCount(toolsCount)
                .setTravelCount(travelCount)
                .setVideoEditorsCount(videoEditorsCount)
                .setWeatherCount(weatherCount);


        return dto;
    }


    /**
     * @Author shen
     * @Description 各类目详细统计
     * @Date 16:19 2022/9/15
     * @Param [dto, appList, lastSubmitTime]
     * @return com.finance.cooperate.feature.dto.ScrapyAppsDTO
     **/
    private ScrapyAppsDTO getCategoriesMap(ScrapyAppsDTO dto, List<App> appList, Date lastSubmitTime) {

        Set<String> appTempSet = new HashSet<>();
        for (App app : appList) {
            if (!StringUtil.isEmptyOrNvl(app.getAppPackageName())) {
                appTempSet.add(app.getAppPackageName().toLowerCase());
            }
        }


        ScrapyAppCategoriesEnum[] enums = ScrapyAppCategoriesEnum.values();

        Map<String, ScrapyAppsMapDTO> scrapyTypeMap = new HashMap<>();

        for (ScrapyAppCategoriesEnum e : enums) {

            if (e == ScrapyAppCategoriesEnum.Top_Overall || e == ScrapyAppCategoriesEnum.Top_Apps || e == ScrapyAppCategoriesEnum.Top_New) {
                continue;
            }


            Integer matchCount = 0, monetizationIsFreeSum = 0, monetizationHasIapSum = 0, monetizationHasAdsSum = 0,
                    monetizationPriceSum = 0, monetizationPriceNotZeroCount = 0, ratingCountSum = 0, ratingCountMin = null,
                    ratingCountMax = null, countriesLenSum = 0, countriesLenMin = null,
                    langLenSum = 0, langLenMin = null, langLenLt5 = 0, downloadSizeSum = 0, inferredFemalePercentSum = 0;


            Float ratingStarsSum = 0f, ratingStarsMin = null, ratingStarsMax = null;

            Long downloadsSum = 0L, downloadsMin = null;


            Map<Integer, Integer> contentRatingValueMap = new HashMap<>(), inferredGenderClassificationMap = new HashMap<>(),
                    inferredAgePercentagesMap = new HashMap<>();


            // 一个类别的app
            List<ScrapyAppCategoriesDTO> scrapyAppLists = scrapyAppsCacheService.getByCategories(e.getCode());

            for (ScrapyAppCategoriesDTO scrapy: scrapyAppLists) {

                if (appTempSet.contains(scrapy.getStoresId().toLowerCase())) {// 匹配上了

                    matchCount ++;

                    String monetizationIsFree = scrapy.getMonetizationIsFree();
                    if (!StringUtil.isEmptyOrNvl(monetizationIsFree)) {

                        int value = Integer.parseInt(monetizationIsFree);

                        monetizationIsFreeSum += value;
                    }


                    String monetizationHasIaps = scrapy.getMonetizationHasIaps();
                    if (!StringUtil.isEmptyOrNvl(monetizationHasIaps)) {

                        int value = Integer.parseInt(monetizationHasIaps);

                        monetizationHasIapSum += value;

                    }


                    String monetizationHasAds = scrapy.getMonetizationHasAds();
                    if (!StringUtil.isEmptyOrNvl(monetizationHasAds)) {

                        int value = Integer.parseInt(monetizationHasAds);

                        monetizationHasAdsSum += value;

                    }


                    String monetizationPrice = scrapy.getMonetizationPrice();
                    if (!StringUtil.isEmptyOrNvl(monetizationPrice)) {

                        int value = Integer.parseInt(monetizationPrice);

                        monetizationPriceSum += value;

                        if (value > 0) {
                            monetizationPriceNotZeroCount ++;
                        }

                    }


                    String ratingStars = scrapy.getRatingStars();
                    if (!StringUtil.isEmptyOrNvl(ratingStars)) {

                        float value = Float.parseFloat(ratingStars);

                        ratingStarsSum += value;

                        if (ratingStarsMax == null || ratingStarsMax < value) {
                            ratingStarsMax = value;
                        }

                        if (ratingStarsMin == null || ratingStarsMin > value) {
                            ratingStarsMin = value;
                        }

                    }


                    String ratingCount = scrapy.getRatingCount();
                    if (!StringUtil.isEmptyOrNvl(ratingCount)) {
                        int value = Integer.parseInt(ratingCount);
                        ratingCountSum += value;

                        if (ratingCountMax == null || ratingCountMax < value) {
                            ratingCountMax = value;
                        }

                        if (ratingCountMin == null || ratingCountMin > value) {
                            ratingCountMin = value;
                        }

                    }

                    String downloads = scrapy.getDownloads();
                    if (!StringUtil.isEmptyOrNvl(downloads)) {
                        long value = Long.parseLong(downloads);

                        downloadsSum += value;

                        if (downloadsMin == null || downloadsMin > value) {
                            downloadsMin = value;
                        }


                    }

                    String countries = scrapy.getCountries();
                    if (!StringUtil.isEmptyOrNvl(countries)) {

                        int length = countries.split(",").length;

                        countriesLenSum += length;

                        if (countriesLenMin == null || countriesLenMin > length) {
                            countriesLenMin = length;
                        }


                    }


                    String langs = scrapy.getLangs();

                    if (!StringUtil.isEmptyOrNvl(langs)) {

                        int length = langs.split(",").length;

                        langLenSum += length;
                        if (langLenMin == null || langLenMin > length) {
                            langLenMin = length;
                        }

                        if (length < 5) {
                            langLenLt5 ++;
                        }

                    }


                    String downloadSize = scrapy.getDownloadSize();

                    if (!StringUtil.isEmptyOrNvl(downloadSize)) {
                        int value = Integer.parseInt(downloadSize);

                        downloadSizeSum += value;

                    }


                    String contentRatingValue = scrapy.getContentRatingValue();
                    if (!StringUtil.isEmptyOrNvl(contentRatingValue)) {

                        Integer valueMap = ScrapyCache.getTypeContentRatingValueMap(contentRatingValue);

                        Integer value = contentRatingValueMap.getOrDefault(valueMap, 0);

                        contentRatingValueMap.put(valueMap, ++ value);

                    }



                    String inferredGenderClassification = scrapy.getInferredGenderClassification();
                    if (!StringUtil.isEmptyOrNvl(inferredGenderClassification)) {

                        Integer valueMap = ScrapyCache.getTypeInferredGenderClassificationMap(inferredGenderClassification);

                        Integer value = inferredGenderClassificationMap.getOrDefault(valueMap, 0);

                        inferredGenderClassificationMap.put(valueMap, ++ value);

                    }

                    String inferredAgePercentages = scrapy.getInferredAgePercentages();
                    if (!StringUtil.isEmptyOrNvl(inferredAgePercentages)) {

                        Map<String, Integer> map = JSON.parseObject(inferredAgePercentages, HashMap.class);

                        Integer maxPercentage = 0;
                        String maxKey = "";

                        for (Map.Entry<String, Integer> entry : map.entrySet()) {

                            Integer agePercentages = entry.getValue();

                            if (!StringUtil.isEmptyOrNvl(agePercentages)) {

                                if (agePercentages > maxPercentage) {

                                    maxPercentage = agePercentages;
                                    maxKey = entry.getKey();

                                }

                            }

                        }

                        if (maxPercentage > 0) {
                            Integer valueMap = ScrapyCache.getTypeInferredAgePercentagesMap(maxKey);

                            Integer value = inferredAgePercentagesMap.getOrDefault(valueMap, 0);

                            inferredAgePercentagesMap.put(valueMap, ++ value);

                        }
                    }

                    String inferredFemalePercent = scrapy.getInferredFemalePercent();
                    if (!StringUtil.isEmptyOrNvl(inferredFemalePercent)) {

                        int value = Integer.parseInt(inferredFemalePercent);

                        inferredFemalePercentSum += value;


                    }

                }

            }


            // 生成内部特征
            ScrapyAppsMapDTO info = new ScrapyAppsMapDTO();
            if (matchCount > 0) {
                info
                        .setMonetizationIsFreeAvg((float) monetizationIsFreeSum / matchCount)
                        .setMonetizationIsFreeSum(monetizationIsFreeSum)
                        .setMonetizationHasIapAvg((float) monetizationHasIapSum / matchCount)
                        .setMonetizationHasIapSum(monetizationHasIapSum)
                        .setMonetizationHasAdsAvg((float) monetizationHasAdsSum / matchCount)
                        .setMonetizationHasAdsSum(monetizationHasAdsSum)
                        .setMonetizationPriceAvg((float) monetizationPriceSum / matchCount)
                        .setMonetizationPriceSum(monetizationPriceSum)
                        .setMonetizationPriceNonZeroCount(monetizationPriceNotZeroCount)
                        .setRatingStarsAvg(ratingStarsSum / matchCount)
                        .setRatingStarsMin(ratingStarsMin)
                        .setRatingStarsMax(ratingStarsMax)
                        .setRatingCountAvg((float) ratingCountSum / matchCount)
                        .setRatingCountMin(ratingCountMin)
                        .setRatingCountMax(ratingCountMax)
                        .setDownloadsAvg((double) downloadsSum / matchCount)
                        .setDownloadsMin(downloadsMin)
                        .setCountriesLenAvg((float) countriesLenSum / matchCount)
                        .setCountriesLenMin(countriesLenMin)
                        .setLangLenAvg((float) langLenSum / matchCount)
                        .setLangLenMin(langLenMin)
                        .setLangLenLt5(langLenLt5)
                        .setDownloadSizeAvg((float) downloadSizeSum / matchCount)
                        .setDownloadSizeSum(downloadSizeSum)
                        .setContentRatingValueMap(contentRatingValueMap)
                        .setInferredGenderClassificationMap(inferredGenderClassificationMap)
                        .setInferredAgePercentagesMap(inferredAgePercentagesMap)
                        .setInferredFemalePercentAvg((float) inferredFemalePercentSum / matchCount);


            }


            scrapyTypeMap.put(e.getCode(), info);

        }

        dto.setScrapyTypeMap(scrapyTypeMap);

        return dto;

    }


}
